<?php
/**
 * GioCMS
 * 
 * LICENSE
 *
 * This source file is subject to the GNU GENERAL PUBLIC LICENSE Version 2 
 * that is bundled with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://www.gnu.org/licenses/gpl-2.0.txt
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@ninhgio.com so we can send you a copy immediately.
 * 
 * @copyright	Copyright (c) 2010-2011 GioCMS (http://cms.ninhgio.com)
 * @license		http://www.gnu.org/licenses/gpl-2.0.txt GNU GENERAL PUBLIC LICENSE Version 2
 * @author		NinhGio - ninhgio@gmail.com
 * @since		1.0
 */

class Gio_Core_Controller
{
	private $_module = null;
	private $_controller = null;
	private $_action = null;
	private $_template = 'default';
	private $_layout = 'default';
	private $_content = null;
	private $_noRender = false;
	private $_disableLayout = false;
	/**
	 * @param Gio_Core_Request
	 */
	private $_request = null;
	/**
	 * @param Gio_Core_Response
	 */
	private $_response = null;
	
	public $view = null;
	
	/**
	 * @param Gio_Core_Controller
	 */
	private static $_instance = null;
	
	/**
	 * @return Gio_Core_Controller
	 */
	public static function getIntance()
	{
		if (null == self::$_instance) {
			self::$_instance = new self();
		}
		return self::$_instance;
	}
	
	public function __construct()
	{
		$this->view 	 = Gio_Core_View::getInstance();
		$this->_request  = Gio_Core_Request::getInstance();
		$this->_response = Gio_Core_Response::getInstance();
	}
	
	public function getModuleName()
	{
		return $this->_module;
	}
	
	/**
	 * @return Gio_Core_Controller
	 */
	public function setModuleName($name)
	{
		if ($name == 'GLOBAL') {
			$name = Gio_Core_Request::getInstance()->getParam('module', 'index');
		}
		$this->_module = strtolower($name);
		Gio_Core_Request::getInstance()->setParam('module', $this->_module);
		return $this;
	}
	
	public function getControllerName()
	{
		return $this->_controller;
	}
	
	/**
	 * @return Gio_Core_Controller
	 */
	public function setControllerName($name)
	{
		if ($name == 'GLOBAL') {
			$name = Gio_Core_Request::getInstance()->getParam('controller', 'index');
		}
		$this->_controller = strtolower($name);
		Gio_Core_Request::getInstance()->setParam('controller', $this->_controller);
		return $this;
	}
	
	public function getActionName()
	{
		return $this->_action;
	}
	
	/**
	 * @return Gio_Core_Controller
	 */
	public function setActionName($name)
	{
		if ($name == 'GLOBAL') {
			$name = Gio_Core_Request::getInstance()->getParam('action', 'index');
		}
		$this->_action = strtolower($name);
		Gio_Core_Request::getInstance()->setParam('action', $this->_action);
		return $this;
	}
	
	public function getLayout()
	{
		if (isset($this->_view->APP_LAYOUT) && $this->_view->APP_LAYOUT) {
			return $this->_view->APP_LAYOUT;
		}
		return $this->_layout;
	}
	
	/**
	 * @return Gio_Core_Controller
	 */
	public function setLayout($name)
	{
		$this->_view = Gio_Core_View::getInstance();
		$this->_view->APP_LAYOUT = $name;
		$this->_layout = strtolower($name);
		return $this;
	}
	
	public function getTemplate()
	{
		return $this->_template;
	}
	
	/**
	 * @return Gio_Core_Controller
	 */
	public function setTemplate($name)
	{
		$this->_view = Gio_Core_View::getInstance();
		$this->_view->APP_TEMPLATE = $name;
		$this->_template = strtolower($name);
		return $this;
	}
	
	public function setNoRender()
	{
		$this->_noRender = true;
	}
	
	/**
	 * @return Gio_Core_Request
	 */
	public function getRequest()
	{
		$this->_request = Gio_Core_Request::getInstance();
		return $this->_request;
	}
	
	/**
	 * @return Gio_Core_Response
	 */
	public function getResponse()
	{
		return $this->_response;
	}
	
	/**
	 * @return Gio_Core_Controller
	 */
	public function disableLayout()
	{
		$this->_disableLayout = true;
		return $this;
	}
	
	public function getDisableLayout()
	{
		return $this->_disableLayout;
	}
	
	public function getNoRender()
	{
		return $this->_noRender;
	}
	
	public function dispatch()
	{
		$this->view = Gio_Core_View::getInstance();
		$controllerFront = Gio_Core_Controller::getIntance();
		/**
		 * XML
		 */
		$xmlFilename = array(
							$this->_module,
							$this->_controller,
							$this->_action
					); 
		$xmlFilename = implode('_', $xmlFilename);
		$blocksData = array();
		$xmlFile = TEMPLATE_DIR . DS . $this->view->APP_TEMPLATE . DS . 'data' . DS . $xmlFilename . '.xml';
		if ($this->view->getAdminSection()) {
			$xmlFile = TEMPLATE_DIR . DS . $this->view->APP_TEMPLATE . DS . 'data' . DS . $this->view->APP_TEMPLATE . '.xml';
		}
		if (file_exists($xmlFile)) {
			$xmlData = simplexml_load_file($xmlFile);
			$blocksData = $xmlData->block;
		}
		
		/**
		 * Check file html cache 
		 */
		$globalConfig = Gio_Core_Config_Xml::getConfig();
		$configs = Gio_Core_Config_Xml::getConfig('cache');
		$checkCache = false;
		if ($configs->enable == 'true' && !$this->view->getAdminSection()) {
			$cacheName = $xmlFilename;
			$postParams = $this->_request->getPostParams();
			$getParams = $this->_request->getParams();
			
			$json = new Services_JSON();
			$cacheParams = (!empty($postParams)) ? base64_encode($json->encodeUnsafe($postParams)) : null;
			$cacheParams .= (!empty($getParams)) ? base64_encode($json->encodeUnsafe($getParams)) : null;
			
			$cacheKey = md5($cacheName . $this->view->APP_TEMPLATE . $cacheParams . base64_encode($json->encodeUnsafe($globalConfig)));
			$cacheType = 'actions';
								
			$cacheTimeout = isset($configs->timeout) ? $configs->timeout : 3600;
			if ($blocksData) {
				foreach ($blocksData as $index => $block) {
					if ($block->block_name == 'MAIN_CONTENT' && isset($block->cache->enable)
							&& $block->cache->enable == 'true') 
					{
						$cacheTimeout = isset($block->cache->timeout) ? $block->cache->timeout : 3600;
						/**
						 * Create html file cache
						 */
						if (($checkCache = Gio_Core_Cache::isCached($cacheType, $cacheKey, $cacheTimeout))) {
							$html = $this->view->render(Gio_Core_Cache::_generateFileName($cacheType, $cacheKey));
							return $html;
						}
					}
				}	
			}
		}
		
		$ucfModule	     	 = ucfirst($this->_module);
		$ucfController   	 = ucfirst($this->_controller);
		$controllerClassName = array(
								'Modules',
								$ucfModule,
								'Controllers',
								$ucfController
							); 
		$controllerClassName = implode('_', $controllerClassName);
		
		if (!class_exists($controllerClassName)) {
			Modules_Core_Services_Exception::error('CLASS_NOT_FOUND', $controllerClassName);
		}
		$controllerClass	 = new $controllerClassName();
		
		/**
		 * Call init function
		 */
		if (method_exists($controllerClass, 'init')) {
			$controllerClass->init();
		}
		
		self::$_instance 	 = $controllerClass;
		
		if (!method_exists($controllerClass, $this->_action . 'Action')) {
			Modules_Core_Services_Exception::error('ACTION_NOT_FOUND', $controllerClassName . '::' . $this->_action . 'Action');
			return;
		}
		call_user_func(array($controllerClass, $this->_action . 'Action'));
		$actionCache = array(
			'enable' 	=> false,
			'timeout'	=> 0
		);
		
		if (!Gio_Core_Controller::getIntance()->getDisableLayout()) {
			$widgetObject = Gio_Core_Widget::getIntance();
			if ($blocksData) {
				foreach ($blocksData as $index => $block) {
					if (!isset($block->visible) || (string)$block->visible != 'false') {
						if ($block->type == 'widget') {
							/**
							 * Set Widget User Params
							 */
							$userParams = (isset($block->params)) ? (array)$block->params : null;
							$paramString = null;
							if ($userParams) {
								$request = $widgetObject->getRequest();
								foreach ($userParams as $paramIndex => $param) {
									switch ($param) {
										case 'GLOBAL':
											$userParams[$paramIndex] = $request->getParam($paramIndex);
											$param = $request->getParam($paramIndex);
											break;
										default:
											//$request->setParam($paramIndex, $param);
											break;
									}
									
									$paramString .= ($paramString) ? '|' : null;
									$paramString .= $paramIndex . '=' . $param;
								}
							}
							$userParams['module'] = $block->module;
							$userParams['widget'] = $block->name;
							
							if (isset($block->load) && $block->load == 'ajax') {
								$this->view->module 	  = $block->module;
								$this->view->widget 	  = $block->name;
								$this->view->action 	  = $block->action;
								$this->view->cacheEnable  = (isset($block->cache->enable) && $block->cache->enable == 'true') 
																	? true : false;
								$this->view->cacheTimeout = (isset($block->cache->timeout) && $block->cache->timeout > 0) 
																	? $block->cache->timeout : 3600;
								$this->view->params = $paramString;
								$this->view->uuid   = uniqid();
								/**
								 * Loading Js & Css
								 */
								$widgetViewFile = TEMPLATE_DIR . DS . $this->view->APP_TEMPLATE . DS . 'modules' 
									. DS . $block->module . DS . 'widgets' . DS . $block->name
									. DS . $block->action . '.phtml';
								if (file_exists($widgetViewFile)) {
									$jsCss = $this->view->render($widgetViewFile);
								}
									
								/**
								 * Render Ajax Script 
								 */
								$widgetViewFile = ROOT_DIR . DS . 'modules' . DS . 'core' . DS . 'views' 
														. DS . 'core' . DS . 'widgets' . DS . 'ajax.phtml';	
			
								$this->view->{$block->block_name} = $this->view->render($widgetViewFile);	
							} else {
								$cacheEnable = (isset($block->cache->enable) && $block->cache->enable == 'true')
													? true : false;
								$cacheTimeout = (isset($block->cache->timeout) && $block->cache->timeout > 0)
													? $block->cache->timeout : 0;					 
								$widgetObject->setTemplate($this->view->APP_TEMPLATE)
											->setModuleName($block->module)
											->setWidgetName($block->name)
											->setActionName($block->action)
											->setCacheEnable($cacheEnable)
											->setCacheTimeout($cacheTimeout)
											->setParams($userParams);
								$this->view->{$block->block_name} = $widgetObject->dispatch();
							}
						} elseif ($block->block_name == 'MAIN_CONTENT') {
							$actionCache['enable'] = (isset($block->cache->enable) && $block->cache->enable == 'true')
															? true : false;
							$actionCache['timeout'] = (isset($block->cache->timeout) && $block->cache->timeout > 0)
															? $block->cache->timeout : 0;
						}
					}
				}
			}
		}
		
		$actionViewFile = TEMPLATE_DIR . DS . $this->view->APP_TEMPLATE . DS . 'modules' 
								. DS . $this->_module . DS . $this->_controller
								. DS . $this->_action . '.phtml';
		if (!file_exists($actionViewFile)) {
			/**
			 * Default action view file
			 */
			$actionViewFile = ROOT_DIR . DS . 'modules' . DS . $this->_module 
								. DS . 'views' . DS . $this->_controller
								. DS . $this->_action . '.phtml';
		}	
		
		if (!Gio_Core_Controller::getIntance()->getNoRender()) {
			$content = $controllerClass->view->render($actionViewFile);
			$this->view->MAIN_CONTENT = $content;
		}
		
		if (!Gio_Core_Controller::getIntance()->getDisableLayout()) {
			$xmlFilename = (isset($this->view->APP_LAYOUT) && $this->view->APP_LAYOUT) 
												? $this->view->APP_LAYOUT : $xmlFilename; 
			$layoutFile = TEMPLATE_DIR . DS . $this->view->APP_TEMPLATE . DS . 'layouts' . DS . $xmlFilename . '.phtml';
			if ($this->view->getAdminSection()) {
				$layoutFile = TEMPLATE_DIR . DS . $this->view->APP_TEMPLATE . DS . 'layouts' . DS . $this->view->APP_TEMPLATE . '.phtml';
			}
			
			/**
			 * Check param __GIOCMS_ERROR__
			 */
			if (Gio_Core_Request::getInstance()->getParam('__GIOCMS_ERROR__') == true) {
				$layoutFile = TEMPLATE_DIR . DS . $this->_template . DS . 'layouts' . DS . $this->_layout . '.phtml';
			}
			
			$return = $this->view->render($layoutFile);
			if (!$checkCache && $configs->enable == 'true' && !$this->view->getAdminSection()
							&& $actionCache['enable'] == true) 
			{
				$cacheCompress = (isset($configs->compress) && $configs->compress == 'true')
										? true : false;
				$cacheContent = $this->view->generateTitle()
								 . $this->view->generateScripts()
								 . $this->view->generateStyles() . $return;
				Gio_Core_Cache::cache($cacheType, $cacheKey, $cacheContent, $cacheCompress);
			}
			
			return $return;
		} elseif (!Gio_Core_Controller::getIntance()->getNoRender()) {
			return $content;
		}
	}
	
	public function redirect($url)
	{
		$url = (null == $url) ? 'index.php' : $url;
		header('Location: ' . $url);
		exit();
	}
}